package proxy

import (
	. "db-sharding/mysql"
	"db-sharding/sqlparser"
	"db-sharding/system/log4go"
	"fmt"
	"github.com/pingcap/parser/ast"
	driver "github.com/pingcap/tidb/types/parser_driver"
	"strings"
)

var nstring = sqlparser.String

func (c *Conn) handleSet(stmt *sqlparser.Set) error {
	if len(stmt.Exprs) != 1 {
		return fmt.Errorf("must set one item once, not %s", nstring(stmt))
	}

	k := string(stmt.Exprs[0].Name.Name)

	switch strings.ToUpper(k) {
	case `AUTOCOMMIT`:
		return c.handleSetAutoCommit(stmt.Exprs[0].Expr)
	case `NAMES`:
		return c.handleSetNames(stmt.Exprs[0].Expr)
	default:
		//return fmt.Errorf("set %s is not supported now", k)
		c.writeOK(nil)
		return nil
	}
}

func (c *Conn) handleSetNew(stmt *ast.SetStmt) error {
	if len(stmt.Variables) != 1 {
		log4go.Error("must set one item once")
		return fmt.Errorf("must set one item once")
	}

	k := stmt.Variables[0].Name
	switch strings.ToUpper(k) {
	case `AUTOCOMMIT`:
		//log4go.Debug("设置自动提交")
		switch v := stmt.Variables[0].Value.(type) {
		case *driver.ValueExpr:
			//log4go.Debug("设置自动提交值",v.GetInt64())
			return c.handleSetAutoCommitNew(v.GetInt64())
		}
	case `SETNAMES`:
		//log4go.Debug("设置SETNAMES")
		switch v := stmt.Variables[0].Value.(type) {
		case *driver.ValueExpr:
			return c.handleSetNamesNew(v.GetDatumString())
		}
	default:
		//log4go.Debug("设置属性",k, "未实现")
		return c.writeOK(nil)
	}
	return nil
}

func (c *Conn) handleSetAutoCommit(val sqlparser.ValExpr) error {
	value, ok := val.(sqlparser.NumVal)
	if !ok {
		return fmt.Errorf("set autocommit error")
	}
	switch value[0] {
	case '1':
		c.status |= SERVER_STATUS_AUTOCOMMIT
	case '0':
		c.status &= ^SERVER_STATUS_AUTOCOMMIT
	default:
		return fmt.Errorf("invalid autocommit flag %s", value)
	}

	return c.writeOK(nil)
}

func (c *Conn) handleSetAutoCommitNew(val int64) error {
	switch val {
	case 1:
		c.status |= SERVER_STATUS_AUTOCOMMIT
	case 0:
		c.status &= ^SERVER_STATUS_AUTOCOMMIT
	default:
		return fmt.Errorf("invalid autocommit flag %s", val)
	}

	return c.writeOK(nil)
}

func (c *Conn) handleSetNames(val sqlparser.ValExpr) error {
	value, ok := val.(sqlparser.StrVal)
	if !ok {
		return fmt.Errorf("set names charset error")
	}

	charset := strings.ToLower(string(value))
	cid, ok := CharsetIds[charset]
	if !ok {
		return fmt.Errorf("invalid charset %s", charset)
	}

	c.charset = charset
	c.collation = cid

	return c.writeOK(nil)
}

func (c *Conn) handleSetNamesNew(charset string) error {
	cid, ok := CharsetIds[charset]
	if !ok {
		return fmt.Errorf("invalid charset %s", charset)
	}

	c.charset = charset
	c.collation = cid

	return c.writeOK(nil)
}
